<?php


namespace NanQi\Hope;


use Faker\Factory;
use Faker\Generator;
use Hyperf\AsyncQueue\Driver\DriverFactory;
use Hyperf\AsyncQueue\JobInterface;
use Hyperf\Cache\CacheManager;
use Hyperf\Cache\Driver\CoroutineMemoryDriver;
use Hyperf\Cache\Driver\DriverInterface;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface;
use Hyperf\Redis\RedisFactory;
use Hyperf\Redis\RedisProxy;
use Hyperf\Server\ServerFactory;
use NanQi\Hope\Base\BaseEvent;
use NanQi\Hope\Service\JwtService;
use NanQi\Hope\Traits\ResponseFormatTrait;
use Psr\EventDispatcher\EventDispatcherInterface;
use Swoole\Server;

trait Helper
{
    use ResponseFormatTrait;

    /**
     * 获取Redis
     * @param $name
     * @return RedisProxy
     */
    protected function getRedis($name = 'default') : RedisProxy
    {
        /** @var RedisFactory $redisFactory */
        $redisFactory = di(RedisFactory::class);
        return $redisFactory->get($name);
    }

    /**
     * 获取业务redis对象
     * @return RedisProxy
     */
    protected function getRedisBusiness() : RedisProxy
    {
        $redis = $this->getRedis('business');
        if (!$redis) {
            $this->errorNotFound('未找到配置的业务redis');
        }

        return $redis;
    }

    /**
     * 获取请求对象
     * @return RequestInterface
     */
    protected function getReq() : RequestInterface
    {
        return di(RequestInterface::class);
    }

    /**
     * 获取响应对象
     * @return ResponseInterface
     */
    protected function getRes() : ResponseInterface
    {
        return di(ResponseInterface::class);
    }

    /**
     * 获取假数据构造器
     * @return Generator
     */
    protected function getFaker() : Generator
    {
        if ($this->isProduct()) {
            throw new \RuntimeException('Faker 只能在非生产环境使用');
        }
        return Factory::create('zh_CN');
    }

    /**
     * 是否生产环境
     * @return bool
     */
    protected function isProduct() : bool
    {
        $appEnv = env('APP_ENV', 'dev');
        return in_array($appEnv, ['prod', 'stag']);
    }

    /**
     * 获取日志
     * @return StdoutLoggerInterface
     */
    protected function getLog() : StdoutLoggerInterface
    {
        return di(StdoutLoggerInterface::class);
    }

    /**
     * 获取授权用户ID
     */
    protected function getAuthId() : int
    {
        /** @var JwtService $jwtService */
        $jwtService = di(JwtService::class);
        $user_id = $jwtService->checkToken();
        if ($user_id === false) {
            return 0;
        }

        return $user_id;
    }

    /**
     * 是否登录
     * @return bool
     */
    protected function isLogin() : bool
    {
        return !!$this->getAuthId();
    }

    /**
     * 获取全局缓存
     */
    protected function getArrayCache() : DriverInterface
    {
        $cacheManager = di(CacheManager::class);
        return $cacheManager->getDriver('array');
    }

    /**
     * 获取当前Server
     * @return Server | \Swoole\Coroutine\Http\Server
     */
    protected function getServer()
    {
        /** @var ServerFactory $serverFactory */
        $serverFactory = di(ServerFactory::class);
        $server = $serverFactory->getServer()->getServer();
        if ($server instanceof Server || $server instanceof \Swoole\Coroutine\Http\Server) {
            return $server;
        }

        throw new \RuntimeException(__METHOD__);
    }

    /**
     * 投递消息
     * @param JobInterface $job
     * @param int $delay
     * @param string $channel
     * @return bool
     */
    protected function mq(JobInterface $job, int $delay = 0, string $channel = 'default') : bool
    {
        /** @var DriverFactory $driverFactory */
        $driverFactory = di(DriverFactory::class);
        return $driverFactory->get($channel)->push($job, $delay);
    }

    /**
     * 触发事件
     * @param BaseEvent $event
     */
    protected function emmitEvent(BaseEvent $event)
    {
        /** @var EventDispatcherInterface $eventDispatcher */
        $eventDispatcher = di(EventDispatcherInterface::class);

        $eventDispatcher->dispatch($event);
    }
}